#include "CEPropertyPane.h"

using namespace SP;
//--------------------------------------------------------------------------------
// Globals
//--------------------------------------------------------------------------------
static CEPropertiesPane* g_pPropertiesPane = NULL;

CEPropertiesPane*  CEGlobalCreatePropertiesPane( wxWindow* parent )
{
	g_pPropertiesPane = new CEPropertiesPane( parent );
	return g_pPropertiesPane;
}

//--------------------------------------------------------------------------------
// CEPropertiesPane
//--------------------------------------------------------------------------------
BEGIN_EVENT_TABLE( CEPropertiesPane, wxPanel )
	EVT_SIZE( CEPropertiesPane::OnSize )
END_EVENT_TABLE( )

CEPropertiesPane::CEPropertiesPane( wxWindow* parent ) : wxPanel( parent )
{	
	SetBackgroundColour( wxColor( 0xC0C0C0 ) );	
}

void CEPropertiesPane::OnSize( wxSizeEvent& event )
{
	wxWindowList wl = GetChildren();
	for ( wxWindowList::iterator it = wl.begin(); it != wl.end(); it++ )
	{
		(*it)->SetInitialSize( event.GetSize() );
	}
}

//--------------------------------------------------------------------------------
// PG base class
//--------------------------------------------------------------------------------
BEGIN_EVENT_TABLE( CEPropertyGrid, wxPropertyGrid )
	EVT_PG_CHANGED( wxID_ANY, CEPropertyGrid::OnPGChange )
END_EVENT_TABLE( )

CEPropertyGrid::CEPropertyGrid() 
	: wxPropertyGrid( g_pPropertiesPane )
{	
	SetInitialSize( g_pPropertiesPane->GetSize() );
}

void CEPropertyGrid::OnPGChange( wxPropertyGridEvent& event )
{
	OnUpdate();
}

void CEPropertyGrid::AppendDistributionVector( wxString label , DistributionVectorProperties& DP )
{
	wxPGChoices tarr;
	tarr.Add( L"Constant", 1 );
	tarr.Add( L"Uniform", 2 );

	wxPGProperty* pName= Append( new wxStringProperty( label + L"  DistributionVector     ", wxPG_LABEL, L"" ) );
	DP.m_pProperties[0]  = pName;
	DP.m_pProperties[1] = AppendIn( pName, new wxEnumProperty( L"DistributionType", wxPG_LABEL, tarr, 1 ) );

	wxPGProperty* pConstant = AppendIn( pName, new wxStringProperty( L"ConstantVector", wxPG_LABEL, L"<composed>" ) );
	DP.m_pProperties[2] = pConstant;
	DP.m_pProperties[3] = AppendIn( pConstant, new wxFloatProperty( L"X" )  );
	DP.m_pProperties[4] = AppendIn( pConstant, new wxFloatProperty( L"Y" )  );
	DP.m_pProperties[5] = AppendIn( pConstant, new wxFloatProperty( L"Z" )  );

	wxPGProperty* pUniform = AppendIn( pName, new wxStringProperty( L"UniformVector", wxPG_LABEL, L"<composed>" ) );
	wxPGProperty* pMax = AppendIn( pUniform, new wxStringProperty( L"Max", wxPG_LABEL, L"<composed>" ) );
	wxPGProperty* pMin = AppendIn( pUniform, new wxStringProperty( L"Min", wxPG_LABEL, L"<composed>" ) );

	DP.m_pProperties[6] = pUniform;
	DP.m_pProperties[7] = pMax;
	DP.m_pProperties[8] = pMin;
	DP.m_pProperties[9] =   AppendIn( pMax, new wxFloatProperty( L"X" )  );
	DP.m_pProperties[10] = AppendIn( pMax, new wxFloatProperty( L"Y" )  );
	DP.m_pProperties[11] = AppendIn( pMax, new wxFloatProperty( L"Z" )  );

	DP.m_pProperties[12] = AppendIn( pMin, new wxFloatProperty( L"X" )  );
	DP.m_pProperties[13] = AppendIn( pMin, new wxFloatProperty( L"Y" )  );
	DP.m_pProperties[14] = AppendIn( pMin, new wxFloatProperty( L"Z" )  );

	UpdateDistributionVector( DP );
}

void CEPropertyGrid::UpdateDistributionVector( DistributionVectorProperties& DP )
{
	int distributionType = DP.m_pProperties[1]->GetValue().GetInteger();

	if ( distributionType == 1 )
	{	
		DP.m_pProperties[2]->Hide( false );
		DP.m_pProperties[6]->Hide( true );
		float x = DP.m_pProperties[3]->GetValue().GetDouble();
		float y = DP.m_pProperties[4]->GetValue().GetDouble();
		float z = DP.m_pProperties[5]->GetValue().GetDouble();
		DP.pRawDistributionVector->SafeSet( &SPDistributionFloatConstant( x ), 
			&SPDistributionFloatConstant( y ), 
			&SPDistributionFloatConstant( z ) );
	}
	else
	{
		DP.m_pProperties[2]->Hide( true );
		DP.m_pProperties[6]->Hide( false );
		float x1 = DP.m_pProperties[9]->GetValue().GetDouble();
		float y1 = DP.m_pProperties[10]->GetValue().GetDouble();
		float z1 = DP.m_pProperties[11]->GetValue().GetDouble();

		float x2 = DP.m_pProperties[12]->GetValue().GetDouble();
		float y2 = DP.m_pProperties[13]->GetValue().GetDouble();
		float z2 = DP.m_pProperties[14]->GetValue().GetDouble();
		DP.pRawDistributionVector->SafeSet( &SPDistributionFloatUniform( x1, x2 ), 
			&SPDistributionFloatUniform( y1, y2 ), 
			&SPDistributionFloatUniform( z1, z2 ) );
	}
}

void CEPropertyGrid::AppendDistributionFloat( wxString label, DistributionFloatProperties& DP )
{
	wxPGChoices tarr;
	tarr.Add( L"Constant", 1 );
	tarr.Add( L"Uniform", 2 );

	wxPGProperty* pName= Append( new wxStringProperty( label + L"  DistributionFloat     ", wxPG_LABEL, L"" ) );
	DP.m_pProperties[0]  = pName;
	DP.m_pProperties[1] = AppendIn( pName, new wxEnumProperty( L"DistributionType", wxPG_LABEL, tarr, 1 ) );


	DP.m_pProperties[2] = AppendIn( pName, new wxFloatProperty( L"ConstantFloat" )  );
	DP.m_pProperties[3] = AppendIn( pName, new wxFloatProperty( L"UniformFloatMax" ) );
	DP.m_pProperties[4] = AppendIn( pName, new wxFloatProperty( L"UniformFloatMin" ) );

	UpdateDistributionFloat( DP );
}

void CEPropertyGrid::UpdateDistributionFloat( DistributionFloatProperties& DP )
{
	int distributionType = DP.m_pProperties[1]->GetValue().GetInteger();

	if ( distributionType == 1 )
	{	
		DP.m_pProperties[2]->Hide( false );
		DP.m_pProperties[3]->Hide( true );
		DP.m_pProperties[4]->Hide( true );
		float x = DP.m_pProperties[2]->GetValue().GetDouble();

		DP.pRawDistributionFloat->SafeSet( &SPDistributionFloatConstant( x ) );
	}
	else
	{
		DP.m_pProperties[2]->Hide( true );
		DP.m_pProperties[3]->Hide( false );
		DP.m_pProperties[4]->Hide( false );
		float x1 = DP.m_pProperties[3]->GetValue().GetDouble();
		float x2 = DP.m_pProperties[4]->GetValue().GetDouble();

		DP.pRawDistributionFloat->SafeSet( &SPDistributionFloatUniform( x1, x2 ) );
	}
}

void CEPropertyGrid::AppendVector( wxString label, VectorProperties& VP )
{
	wxPGProperty* pVector = Append( new wxStringProperty( label + L"  Vector", wxPG_LABEL, L"<composed>" ) );
	VP.m_pProperties[0] = pVector;
	VP.m_pProperties[1] = AppendIn( pVector, new wxFloatProperty( L"X" )  );
	VP.m_pProperties[2] = AppendIn( pVector, new wxFloatProperty( L"Y" )  );
	VP.m_pProperties[3] = AppendIn( pVector, new wxFloatProperty( L"Z" )  );
}

void CEPropertyGrid::UpdateVector( VectorProperties& VP )
{
	VP.m_vValue.x = VP.m_pProperties[1]->GetValue().GetDouble();
	VP.m_vValue.y = VP.m_pProperties[2]->GetValue().GetDouble();
	VP.m_vValue.z = VP.m_pProperties[3]->GetValue().GetDouble();
}
//--------------------------------------------------------------------------------
// PG subclass
//--------------------------------------------------------------------------------


//--------------------------------------------------------------------------------
// CEPGBlendState
//--------------------------------------------------------------------------------
CEPGBlendState::CEPGBlendState( SP::SPModuleBlendState* pModule )
	: m_pModule( pModule )
{
	wxPGChoices arrBlend;
	arrBlend.Add( L"D3D11_BLEND_ZERO", 1 );
	arrBlend.Add( L"D3D11_BLEND_ONE", 2 );
	arrBlend.Add( L"D3D11_BLEND_SRC_COLOR", 3 );
	arrBlend.Add( L"D3D11_BLEND_INV_SRC_COLOR", 4 );
	arrBlend.Add( L"D3D11_BLEND_SRC_ALPHA ", 5 );
	arrBlend.Add( L"D3D11_BLEND_INV_SRC_ALPHA", 6 );
	arrBlend.Add( L"D3D11_BLEND_DEST_ALPHA", 7 );
	arrBlend.Add( L"D3D11_BLEND_INV_DEST_ALPHA", 8 );
	arrBlend.Add( L"D3D11_BLEND_DEST_COLOR", 9 );
	arrBlend.Add( L"D3D11_BLEND_INV_DEST_COLOR", 10 );
	arrBlend.Add( L"D3D11_BLEND_SRC_ALPHA_SAT", 11 );
	arrBlend.Add( L"D3D11_BLEND_BLEND_FACTOR ", 14 );
	arrBlend.Add( L"D3D11_BLEND_INV_BLEND_FACTOR", 15 );
	//	arrBlend.Add( L"D3D11_BLEND_SRC1_COLOR", 16 );
	//	arrBlend.Add( L"D3D11_BLEND_INV_SRC1_COLOR", 17 );
	//	arrBlend.Add( L"D3D11_BLEND_SRC1_ALPHA", 18 );
	//	arrBlend.Add( L"D3D11_BLEND_INV_SRC1_ALPHA", 19 );

	wxPGChoices arrBlend_OP;
	arrBlend_OP.Add( L"D3D11_BLEND_OP_ADD", 1 );
	arrBlend_OP.Add( L"D3D11_BLEND_OP_SUBTRACT", 2 );
	arrBlend_OP.Add( L"D3D11_BLEND_OP_REV_SUBTRACT", 3 );
	arrBlend_OP.Add( L"D3D11_BLEND_OP_MIN", 4 );
	arrBlend_OP.Add( L"D3D11_BLEND_OP_MAX", 5 );

	wxPGChoices arrWriteMark;
	arrWriteMark.Add( L"D3D11_COLOR_WRITE_ENABLE_RED", 1 );
	arrWriteMark.Add( L"D3D11_COLOR_WRITE_ENABLE_GREEN", 2 );
	arrWriteMark.Add( L"D3D11_COLOR_WRITE_ENABLE_BLUE", 4 );
	arrWriteMark.Add( L"D3D11_COLOR_WRITE_ENABLE_ALPHA", 8 );


	Append(  new wxPropertyCategory( L"DX11BlendState" ) );
	m_pProperties[1] = Append(  new wxBoolProperty( L"AlphaToCoverageEnable", wxPG_LABEL, false ) );
	m_pProperties[2] = Append(  new wxBoolProperty( L"IndependentBlendEnable", wxPG_LABEL, false ) );
	m_pProperties[2]->Enable( false );

	wxPGProperty* pRenderTergeProp =  Append( new wxStringProperty( L"RenderTarget", wxPG_LABEL,	L"<composed>" ) );

	m_pProperties[3] = AppendIn( pRenderTergeProp, new wxBoolProperty( L"BlendEnable", wxPG_LABEL, 	false ) );

	m_pProperties[4] = AppendIn( pRenderTergeProp, new wxEnumProperty( L"SrcBlend", wxPG_LABEL, arrBlend ) );
	m_pProperties[5] = AppendIn( pRenderTergeProp, new wxEnumProperty( L"DestBlend", wxPG_LABEL, arrBlend ) );
	m_pProperties[6] = AppendIn( pRenderTergeProp, new wxEnumProperty( L"BlendOp", wxPG_LABEL, arrBlend_OP ) );

	//	arrBlend.RemoveAt( 14 );
	//	arrBlend.RemoveAt( 13 );
	arrBlend.RemoveAt( 9 );
	arrBlend.RemoveAt( 8 );
	arrBlend.RemoveAt( 3 );
	arrBlend.RemoveAt( 2 );

	m_pProperties[7] = AppendIn( pRenderTergeProp, new wxEnumProperty( L"SrcBlendAlpha", wxPG_LABEL, arrBlend ) );
	m_pProperties[8] = AppendIn( pRenderTergeProp, new wxEnumProperty( L"DestBlendAlpha", wxPG_LABEL, arrBlend ) );
	m_pProperties[9] = AppendIn( pRenderTergeProp, new wxEnumProperty( L"BlendOpAlpha", wxPG_LABEL, arrBlend_OP ) );

	m_pProperties[0] = AppendIn( pRenderTergeProp, new wxFlagsProperty( L"WriteMark", wxPG_LABEL, arrWriteMark ) );

	D3D11_BLEND_DESC desc;
	desc.AlphaToCoverageEnable = FALSE;
	desc.IndependentBlendEnable = FALSE;
	desc.RenderTarget[0].BlendEnable = FALSE;
	desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
	desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
	desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
	desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
	desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
	SetValue( desc );
}

void CEPGBlendState::OnUpdate()
{
	D3D11_BLEND_DESC desc;
	GetValue( desc );
	m_pModule->SetStateDesc( desc );
}

void CEPGBlendState::SetValue( const D3D11_BLEND_DESC& desc )
{
	m_pProperties[1]->SetValue( desc.AlphaToCoverageEnable );
	m_pProperties[2]->SetValue( desc.IndependentBlendEnable );
	m_pProperties[3]->SetValue( desc.RenderTarget[0].BlendEnable );
	m_pProperties[4]->SetValue( desc.RenderTarget[0].SrcBlend );
	m_pProperties[5]->SetValue( desc.RenderTarget[0].DestBlend );
	m_pProperties[6]->SetValue( desc.RenderTarget[0].BlendOp );
	m_pProperties[7]->SetValue( desc.RenderTarget[0].SrcBlendAlpha );
	m_pProperties[8]->SetValue( desc.RenderTarget[0].DestBlendAlpha );
	m_pProperties[9]->SetValue( desc.RenderTarget[0].BlendOpAlpha );
	m_pProperties[0]->SetValue( desc.RenderTarget[0].RenderTargetWriteMask );
}

void CEPGBlendState::GetValue( D3D11_BLEND_DESC& desc )
{
	desc.AlphaToCoverageEnable				=		m_pProperties[1]->GetValue( ).GetBool( );
	desc.IndependentBlendEnable				=		m_pProperties[2]->GetValue( ).GetBool( );

	desc.RenderTarget[0].BlendEnable			=		m_pProperties[3]->GetValue( ).GetBool( );
	desc.RenderTarget[0].SrcBlend				=		( D3D11_BLEND )			m_pProperties[4]->GetValue( ).GetInteger( );
	desc.RenderTarget[0].DestBlend			=		( D3D11_BLEND )			m_pProperties[5]->GetValue( ).GetInteger( );
	desc.RenderTarget[0].BlendOp				=		( D3D11_BLEND_OP )	m_pProperties[6]->GetValue( ).GetInteger( );
	desc.RenderTarget[0].SrcBlendAlpha		=		( D3D11_BLEND )			m_pProperties[7]->GetValue( ).GetInteger( );
	desc.RenderTarget[0].DestBlendAlpha	=		( D3D11_BLEND )			m_pProperties[8]->GetValue( ).GetInteger( );
	desc.RenderTarget[0].BlendOpAlpha		=		( D3D11_BLEND_OP )	m_pProperties[9]->GetValue( ).GetInteger( );

	desc.RenderTarget[0].RenderTargetWriteMask = m_pProperties[0]->GetValue( ).GetInteger( );
}


//--------------------------------------------------------------------------------
// CEPGDepthStencilState
//--------------------------------------------------------------------------------
CEPGDepthStencilState::CEPGDepthStencilState( SP::SPModuleDepthStencilState* pModule )
	: m_pModule( pModule )
{
	Append(  new wxPropertyCategory( L"DX11DepthStencilState" ) );
	m_pProperties[0] = Append(  new wxBoolProperty( L"DepthEnable", wxPG_LABEL, false ) );

	wxPGChoices arrDepthWriteMark;
	arrDepthWriteMark.Add( L"D3D11_DEPTH_WRITE_MASK_ZERO", 0 );
	arrDepthWriteMark.Add( L"D3D11_DEPTH_WRITE_MASK_ALL", 1 );
	m_pProperties[1] = Append(  new wxEnumProperty( L"DepthWriteMask", wxPG_LABEL, arrDepthWriteMark ) );

	wxPGChoices arrCF;
	arrCF.Add( L"D3D11_COMPARISON_NEVER", 1 ); 
	arrCF.Add( L"D3D11_COMPARISON_LESS", 2 ); 
	arrCF.Add( L"D3D11_COMPARISON_EQUAL", 3 ); 
	arrCF.Add( L"D3D11_COMPARISON_LESS_EQUAL", 4 ); 
	arrCF.Add( L"D3D11_COMPARISON_GREATER", 5 );
	arrCF.Add( L"D3D11_COMPARISON_NOT_EQUAL", 6 ); 
	arrCF.Add( L"D3D11_COMPARISON_GREATER_EQUAL", 7 ); 
	arrCF.Add( L"D3D11_COMPARISON_ALWAYS", 8 ); 
	m_pProperties[2] = Append(  new wxEnumProperty( L"DepthComparisonFunc", wxPG_LABEL, arrCF ) );

	m_pProperties[3] = Append(  new wxBoolProperty( L"StencilEnable", wxPG_LABEL, false ) );

	m_pProperties[4] = Append(  new wxUIntProperty( L"StencilReadMask ", wxPG_LABEL, D3D11_DEFAULT_STENCIL_READ_MASK ) );
	m_pProperties[5] = Append(  new wxUIntProperty( L"StencilWriteMask ", wxPG_LABEL, D3D11_DEFAULT_STENCIL_WRITE_MASK ) );

	wxPGChoices arrStencil_OP;
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_KEEP", 1 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_ZERO", 2 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_REPLACE", 3 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_INCR_SAT", 4 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_DECR_SAT", 5 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_INVERT", 6 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_INCR", 7 );
	arrStencil_OP.Add( L"D3D11_STENCIL_OP_DECR", 8 );

	wxPGProperty* pFrontFaceProp =  Append( new wxStringProperty( L"FrontFace", wxPG_LABEL,	L"<composed>" ) );
	m_pProperties[6] = AppendIn( pFrontFaceProp, new wxEnumProperty( L"StencilFailOp", wxPG_LABEL, arrStencil_OP ) );
	m_pProperties[7] = AppendIn( pFrontFaceProp, new wxEnumProperty( L"StencilDepthFailOp", wxPG_LABEL, arrStencil_OP ) );	
	m_pProperties[8] = AppendIn( pFrontFaceProp, new wxEnumProperty( L"StencilPassOp", wxPG_LABEL, arrStencil_OP ) );	
	m_pProperties[9] = AppendIn( pFrontFaceProp, new wxEnumProperty( L"StencilFunc", wxPG_LABEL, arrCF ) );

	wxPGProperty* pBackFaceProp =  Append( new wxStringProperty( L"BackFace", wxPG_LABEL,	L"<composed>" ) );
	m_pProperties[10] = AppendIn( pBackFaceProp, new wxEnumProperty( L"StencilFailOp", wxPG_LABEL, arrStencil_OP ) );
	m_pProperties[11] = AppendIn( pBackFaceProp, new wxEnumProperty( L"StencilDepthFailOp", wxPG_LABEL, arrStencil_OP ) );	
	m_pProperties[12] = AppendIn( pBackFaceProp, new wxEnumProperty( L"StencilPassOp", wxPG_LABEL, arrStencil_OP ) );	
	m_pProperties[13] = AppendIn( pBackFaceProp, new wxEnumProperty( L"StencilFunc", wxPG_LABEL, arrCF ) );

	D3D11_DEPTH_STENCIL_DESC desc;
	desc.DepthEnable = TRUE;
	desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	desc.DepthFunc = D3D11_COMPARISON_LESS;
	desc.StencilEnable = FALSE;
	desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
	desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;

	desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
	desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;

	desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
	desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
	desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	SetValue( desc );
}

void CEPGDepthStencilState::OnUpdate()
{
	if ( m_pProperties[4]->GetValue( ).GetInteger( ) > 255 )m_pProperties[4]->SetValue( 255 );
	if ( m_pProperties[5]->GetValue( ).GetInteger( ) > 255 )m_pProperties[5]->SetValue( 255 );

	D3D11_DEPTH_STENCIL_DESC desc;
	GetValue( desc );
	m_pModule->SetStateDesc( desc );
}

void CEPGDepthStencilState::SetValue( const D3D11_DEPTH_STENCIL_DESC& desc )
{
	m_pProperties[0]->SetValue( desc.DepthEnable );
	m_pProperties[1]->SetValue( desc.DepthWriteMask );
	m_pProperties[2]->SetValue( desc.DepthFunc );
	m_pProperties[3]->SetValue( desc.StencilEnable );
	m_pProperties[4]->SetValue( desc.StencilReadMask );
	m_pProperties[5]->SetValue( desc.StencilWriteMask );

	m_pProperties[6]->SetValue( desc.FrontFace.StencilFailOp );
	m_pProperties[7]->SetValue( desc.FrontFace.StencilDepthFailOp );
	m_pProperties[8]->SetValue( desc.FrontFace.StencilPassOp );
	m_pProperties[9]->SetValue( desc.FrontFace.StencilFunc );

	m_pProperties[10]->SetValue( desc.BackFace.StencilFailOp );
	m_pProperties[11]->SetValue( desc.BackFace.StencilDepthFailOp );
	m_pProperties[12]->SetValue( desc.BackFace.StencilPassOp );
	m_pProperties[13]->SetValue( desc.BackFace.StencilFunc );
}

void CEPGDepthStencilState::GetValue( D3D11_DEPTH_STENCIL_DESC& desc )
{
	desc.DepthEnable = m_pProperties[0]->GetValue( ).GetBool( );
	desc.DepthWriteMask = ( D3D11_DEPTH_WRITE_MASK )m_pProperties[1]->GetValue( ).GetInteger( );
	desc.DepthFunc = ( D3D11_COMPARISON_FUNC )m_pProperties[2]->GetValue( ).GetInteger( );
	desc.StencilEnable = m_pProperties[3]->GetValue( ).GetBool( );
	desc.StencilReadMask = m_pProperties[4]->GetValue( ).GetInteger( );
	desc.StencilWriteMask = m_pProperties[5]->GetValue( ).GetInteger( );

	desc.FrontFace.StencilFailOp = ( D3D11_STENCIL_OP )m_pProperties[6]->GetValue( ).GetInteger( );
	desc.FrontFace.StencilDepthFailOp =  ( D3D11_STENCIL_OP )m_pProperties[7]->GetValue( ).GetInteger( );
	desc.FrontFace.StencilPassOp = ( D3D11_STENCIL_OP )m_pProperties[8]->GetValue( ).GetInteger( );
	desc.FrontFace.StencilFunc = ( D3D11_COMPARISON_FUNC )m_pProperties[9]->GetValue( ).GetInteger( );

	desc.BackFace.StencilFailOp = ( D3D11_STENCIL_OP )m_pProperties[10]->GetValue( ).GetInteger( );
	desc.BackFace.StencilDepthFailOp =  ( D3D11_STENCIL_OP )m_pProperties[11]->GetValue( ).GetInteger( );
	desc.BackFace.StencilPassOp = ( D3D11_STENCIL_OP )m_pProperties[12]->GetValue( ).GetInteger( );
	desc.BackFace.StencilFunc = ( D3D11_COMPARISON_FUNC )m_pProperties[13]->GetValue( ).GetInteger( );	
}


//--------------------------------------------------------------------------------
// CEPGRasterizerState
//--------------------------------------------------------------------------------
CEPGRasterizerState::CEPGRasterizerState( SP::SPModuleRasterizerState* pModule )
	: m_pModule( pModule )
{
	wxPGChoices arrCM;
	arrCM.Add( L"D3D11_CULL_NONE", 1 );
	arrCM.Add( L"D3D11_CULL_FRONT", 2 );
	arrCM.Add( L"D3D11_CULL_BACK", 3 );

	wxPGChoices arrFM;
	arrFM.Add( L"D3D11_FILL_WIREFRAME", 2 );
	arrFM.Add( L"D3D11_FILL_SOLID", 3 );

	Append(  new wxPropertyCategory( L"DX11RasterizerState" ) );
	m_pProperties[0] = Append( new wxEnumProperty( L"D3D11_FILL_MODE", wxPG_LABEL, arrFM ) );
	m_pProperties[1] = Append( new wxEnumProperty( L"D3D11_CULL_MODE", wxPG_LABEL, arrCM ) );
	m_pProperties[2] = Append( new wxBoolProperty( L"FrontCounterClockwise" ) );
	m_pProperties[3] = Append( new wxIntProperty( L"DepthBias" ) );
	m_pProperties[4] = Append( new wxFloatProperty( L"DepthBiasClamp" ) );
	m_pProperties[5] = Append( new wxFloatProperty( L"SlopeScaledDepthBias" ) );
	m_pProperties[6] = Append( new wxBoolProperty( L"DepthClipEnable" ) );
	m_pProperties[7] = Append( new wxBoolProperty( L"ScissorEnable" ) );
	m_pProperties[8] = Append( new wxBoolProperty( L"MultisampleEnable" ) );
	m_pProperties[9] = Append( new wxBoolProperty( L"AntialiasedLineEnable" ) );

	D3D11_RASTERIZER_DESC desc;
	desc.FillMode = D3D11_FILL_SOLID;
	desc.CullMode = D3D11_CULL_BACK;
	desc.FrontCounterClockwise = FALSE;
	desc.DepthBias = 0;
	desc.SlopeScaledDepthBias = 0.0f;
	desc.DepthClipEnable = TRUE;
	desc.ScissorEnable = FALSE;
	desc.MultisampleEnable = FALSE;
	desc.AntialiasedLineEnable = FALSE;
	SetValue( desc );
}

void CEPGRasterizerState::OnUpdate()
{
	D3D11_RASTERIZER_DESC desc;
	GetVaule( desc );
	m_pModule->SetStateDesc( desc );
}

void CEPGRasterizerState::SetValue( const D3D11_RASTERIZER_DESC& desc )
{
	m_pProperties[0]->SetValue( desc.FillMode );
	m_pProperties[1]->SetValue( desc.CullMode );
	m_pProperties[2]->SetValue( desc.FrontCounterClockwise );
	m_pProperties[3]->SetValue( desc.DepthBias );
	m_pProperties[4]->SetValue( desc.DepthBiasClamp );
	m_pProperties[5]->SetValue( desc.SlopeScaledDepthBias );
	m_pProperties[6]->SetValue( desc.DepthClipEnable );
	m_pProperties[7]->SetValue( desc.ScissorEnable );
	m_pProperties[8]->SetValue( desc.MultisampleEnable );
	m_pProperties[9]->SetValue( desc.AntialiasedLineEnable );
}

void CEPGRasterizerState::GetVaule( D3D11_RASTERIZER_DESC& desc )
{
	desc.FillMode = ( D3D11_FILL_MODE )m_pProperties[0]->GetValue( ).GetInteger( );
	desc.CullMode = ( D3D11_CULL_MODE )m_pProperties[1]->GetValue( ).GetInteger( );
	desc.FrontCounterClockwise = m_pProperties[2]->GetValue( ).GetBool( );
	desc.DepthBias = m_pProperties[3]->GetValue( ).GetInteger( );
	desc.DepthBiasClamp = m_pProperties[4]->GetValue( ).GetDouble( );
	desc.SlopeScaledDepthBias = m_pProperties[5]->GetValue( ).GetDouble( );
	desc.DepthClipEnable = m_pProperties[6]->GetValue( ).GetBool( );
	desc.ScissorEnable = m_pProperties[7]->GetValue( ).GetBool( );
	desc.MultisampleEnable = m_pProperties[8]->GetValue( ).GetBool( );
	desc.AntialiasedLineEnable = m_pProperties[9]->GetValue( ).GetBool( );
}



//--------------------------------------------------------------------------------
// CEPGEmitterTransform
//--------------------------------------------------------------------------------
CEPGEmitterTransform::CEPGEmitterTransform( SP::SPModuleEmitterTransform* pModule )
{
	m_pModule = pModule;

	AppendVector( L"Start", m_vStart );
	AppendVector( L"End", m_vEnd );
}

void CEPGEmitterTransform::OnUpdate()
{
	UpdateVector( m_vStart );
	UpdateVector( m_vEnd );
	m_pModule->SetParm( m_vStart.m_vValue, m_vEnd.m_vValue );
}

//--------------------------------------------------------------------------------
// CEPGEmitterRotation
//--------------------------------------------------------------------------------
CEPGEmitterRotation::CEPGEmitterRotation( SP::SPModuleEmitterRotation* pModule )
	: CEPGEmitterTransform( pModule )
{

}


//--------------------------------------------------------------------------------
// CEPGEmitterScale
//--------------------------------------------------------------------------------
CEPGEmitterScale::CEPGEmitterScale( SP::SPModuleEmitterScale* pModule )
	: CEPGEmitterTransform( pModule )
{
	m_vStart.m_pProperties[1]->SetValue( 1.0 );
	m_vStart.m_pProperties[2]->SetValue( 1.0 );
	m_vStart.m_pProperties[3]->SetValue( 1.0 );

	m_vEnd.m_pProperties[1]->SetValue( 1.0 );
	m_vEnd.m_pProperties[2]->SetValue( 1.0 );
	m_vEnd.m_pProperties[3]->SetValue( 1.0 );

	OnUpdate();
}


//--------------------------------------------------------------------------------
// CEPGEmitterTranslation
//--------------------------------------------------------------------------------
CEPGEmitterTranslation::CEPGEmitterTranslation( SP::SPModuleEmitterTranslation* pModule )
	: CEPGEmitterTransform( pModule )
{

}


//--------------------------------------------------------------------------------
// CEPGEmitterTranslation
//--------------------------------------------------------------------------------
CEPGEmitterColour::CEPGEmitterColour( SP::SPModuleEmitterColour* pModule )
	: m_pModule( pModule )
{
	wxPGProperty* pVector;

	pVector = Append( new wxStringProperty( "Start RGBA", wxPG_LABEL, L"<composed>" ) );
	m_pProperties[0] = pVector;
	m_pProperties[1] = AppendIn( pVector, new wxFloatProperty( L"R", wxPG_LABEL, 0 )  );
	m_pProperties[2] = AppendIn( pVector, new wxFloatProperty( L"G", wxPG_LABEL, 0 )  );
	m_pProperties[3] = AppendIn( pVector, new wxFloatProperty( L"B", wxPG_LABEL, 0 )  );
	m_pProperties[4] = AppendIn( pVector, new wxFloatProperty( L"A", wxPG_LABEL, 0 )  );

	pVector = Append( new wxStringProperty( L"End RGBA", wxPG_LABEL, L"<composed>" ) );
	m_pProperties[5] = pVector;
	m_pProperties[6] = AppendIn( pVector, new wxFloatProperty( L"R", wxPG_LABEL, 0 )  );
	m_pProperties[7] = AppendIn( pVector, new wxFloatProperty( L"G", wxPG_LABEL, 0 )  );
	m_pProperties[8] = AppendIn( pVector, new wxFloatProperty( L"B", wxPG_LABEL, 0 )  );
	m_pProperties[9] = AppendIn( pVector, new wxFloatProperty( L"A", wxPG_LABEL, 0 )  );
}

void CEPGEmitterColour::OnUpdate()
{
	XMFLOAT4 start, end;
	start.x = m_pProperties[1]->GetValue().GetDouble();
	start.y = m_pProperties[2]->GetValue().GetDouble();
	start.z = m_pProperties[3]->GetValue().GetDouble();
	start.w = m_pProperties[4]->GetValue().GetDouble();

	end.x = m_pProperties[6]->GetValue().GetDouble();
	end.y = m_pProperties[7]->GetValue().GetDouble();
	end.z = m_pProperties[8]->GetValue().GetDouble();
	end.w = m_pProperties[9]->GetValue().GetDouble();

	m_pModule->SetParm( start, end );
}

//--------------------------------------------------------------------------------
CEPGInitVector::CEPGInitVector( SP::SPModuleInitVector* pModule )
	: m_pModule( pModule )
{
	Append( new wxPropertyCategory( L"Init" ) );

	m_vConstant.pRawDistributionVector = pModule->GetConstant();
	AppendDistributionVector( L"Init", m_vConstant );
}

void CEPGInitVector::OnUpdate()
{
	UpdateDistributionVector( m_vConstant );
}

//--------------------------------------------------------------------------------
CEPGVectorOverLife::CEPGVectorOverLife( SP::SPModuleVectorOverLife* pModule )
	: m_pModule( pModule )
{
	m_vStart.pRawDistributionVector = pModule->GetStart();
	m_vEnd.pRawDistributionVector = pModule->GetEnd();
	AppendDistributionVector( L"Start", m_vStart );
	AppendDistributionVector( L"End", m_vEnd );
}

void CEPGVectorOverLife::OnUpdate()
{
	UpdateDistributionVector( m_vStart );
	UpdateDistributionVector( m_vEnd );
}

//--------------------------------------------------------------------------------
CEPGInitFloat::CEPGInitFloat( SP::SPModuleInitFloat* pModule )
	: m_pModule( pModule )
{
	Append( new wxPropertyCategory( L"Init" ) );

	m_fConstant.pRawDistributionFloat = pModule->GetConstant();
	AppendDistributionFloat( L"Init", m_fConstant );
}

void CEPGInitFloat::OnUpdate()
{
	UpdateDistributionFloat( m_fConstant );
}

//-------------------------------------------------------------------------
CEPGFloatOverLife::CEPGFloatOverLife( SP::SPModuleFloatOverLife* pModule )
	: m_pModule( pModule )
{
	m_fStart.pRawDistributionFloat = pModule->GetStart();
	m_fEnd.pRawDistributionFloat = pModule->GetEnd();
	AppendDistributionFloat( L"Start", m_fStart );
	AppendDistributionFloat( L"End", m_fEnd );
}

void CEPGFloatOverLife::OnUpdate()
{
	UpdateDistributionFloat( m_fStart );
	UpdateDistributionFloat( m_fEnd );
}



//-------------------------------------------------------------------------
CEPGBeamTerminal::CEPGBeamTerminal( SP::SPModuleBeamTerminal* pModule )
	: m_pModule( pModule )
{
	m_pProperties[0] = Append( new wxBoolProperty( L"OverLife", wxPG_LABEL, false ) );
	
	AppendVector( L"CP Start", m_vCPStart );	
	AppendVector( L"CP End", m_vCPEnd );
	AppendVector( L"SP Start", m_vSPStart );
	AppendVector( L"SP End", m_vSPEnd );

	m_vCPEnd.m_pProperties[0]->Hide( true );
	m_vSPEnd.m_pProperties[0]->Hide( true );
}

void CEPGBeamTerminal::OnUpdate()
{
	UpdateVector( m_vCPStart );
	UpdateVector( m_vSPStart );
	UpdateVector( m_vCPEnd );
	UpdateVector( m_vSPEnd );

	bool bOverLife = m_pProperties[0]->GetValue().GetBool();
	m_vCPEnd.m_pProperties[0]->Hide( !bOverLife );
	m_vSPEnd.m_pProperties[0]->Hide( !bOverLife );

	if ( bOverLife )
	{
		m_pModule->SetCP( m_vCPStart.m_vValue, m_vCPEnd.m_vValue );
		m_pModule->SetSP( m_vSPStart.m_vValue, m_vSPEnd.m_vValue );
	}
	else
	{
		m_pModule->SetCP( m_vCPStart.m_vValue );
		m_pModule->SetSP( m_vSPStart.m_vValue );
	}
}

//-------------------------------------------------------------------------
CEPGBeamShape::CEPGBeamShape( SP::SPModuleBeamShape* pModule )
	: m_pModule( pModule )
{
	wxPGChoices arrShapeType;
	arrShapeType.Add( L"POINT", 0 );
	arrShapeType.Add( L"LINE", 1 );
	arrShapeType.Add( L"CURVE", 2 );
	arrShapeType.Add( L"CIRCLE", 3 );

	m_pProperties[0] = Append( new wxEnumProperty( L"ShapeType", wxPG_LABEL, arrShapeType, 0 ) );
	AppendVector( L"CenterStart", m_vCenterStart );
	m_pProperties[1] = Append( new wxFloatProperty( L"RadiusStart", wxPG_LABEL, 1.0f ) );
	AppendVector( L"CenterEnd", m_vCenterEnd );
	m_pProperties[2] = Append( new wxFloatProperty( L"RadiusEnd", wxPG_LABEL, 1.0f ) );

	m_vCenterStart.m_pProperties[0]->Hide( true );
	m_vCenterEnd.m_pProperties[0]->Hide( true );
	m_pProperties[1]->Hide( true );
	m_pProperties[2]->Hide( true );
}

void CEPGBeamShape::OnUpdate()
{
	UpdateVector( m_vCenterStart );
	UpdateVector( m_vCenterEnd );

	int shapeType = m_pProperties[0]->GetValue().GetInteger();
	bool isCircle = ( shapeType == 3 );

	m_vCenterStart.m_pProperties[0]->Hide( !isCircle );
	m_vCenterEnd.m_pProperties[0]->Hide( !isCircle );
	m_pProperties[1]->Hide( !isCircle );
	m_pProperties[2]->Hide( !isCircle );

	m_pModule->SetType( shapeType );
	XMFLOAT4 start, end;
	start.x = m_vCenterStart.m_vValue.x;
	start.y = m_vCenterStart.m_vValue.y;
	start.z = m_vCenterStart.m_vValue.z;
	start.w = m_pProperties[1]->GetValue().GetDouble();

	end.x = m_vCenterEnd.m_vValue.x;
	end.y = m_vCenterEnd.m_vValue.y;
	end.z = m_vCenterEnd.m_vValue.z;
	end.w = m_pProperties[2]->GetValue().GetDouble();

	m_pModule->SetCircle( start, end );
}





//--------------------------------------------------------------------------------
// CEPGEmitter
//--------------------------------------------------------------------------------
CEPGEmitter::CEPGEmitter( SP::SPEmitter* pEmitter )
	: m_pEmitterBase( pEmitter )
{
	Append( new wxPropertyCategory( L"Emitter" ) );
	m_pPropertiesBase[0] = Append( new wxFloatProperty( L"Duration", wxPG_LABEL, 1.0f ) );
	m_pPropertiesBase[1] = Append( new wxFloatProperty( L"Loops", wxPG_LABEL, 1.0f ) );
}

void CEPGEmitter::OnUpdate()
{
	float duration = m_pPropertiesBase[0]->GetValue().GetDouble();
	if ( duration <= 0.0f )
	{
		m_pPropertiesBase[0]->SetValue( 1.0f );
		m_pEmitterBase->SetDuration( 1.0f );
	}
	else
	{
		m_pEmitterBase->SetDuration( duration );
	}

	float loops = m_pPropertiesBase[1]->GetValue().GetDouble();
	m_pEmitterBase->SetLoops( loops );
}

//--------------------------------------------------------------------------------
// CEPGEmiitterMesh
//--------------------------------------------------------------------------------
CEPGEmitterMesh::CEPGEmitterMesh( SP::SPEmitterMesh* pEmitter )
	: CEPGEmitter( pEmitter ), m_pEmitter( pEmitter )
{
	m_strFilePath = L""; 
	Append( new wxPropertyCategory( L"MeshEmitter" ) );
	m_pProperties[0] = Append( new wxFileProperty( L"OBJ path" ) );

	m_pProperties[1] = Append( new wxBoolProperty( L"EnableLighting", wxPG_LABEL, true ) );
	m_pProperties[2] = Append( new wxBoolProperty( L"EnableTextureMapping", wxPG_LABEL, true ) );
}

void CEPGEmitterMesh::OnUpdate()
{
	CEPGEmitter::OnUpdate();

	wxString path =m_pProperties[0]->GetValue().GetString();
	if ( path != m_strFilePath )
	{
		if ( path.EndsWith(".obj") )
		{
			m_strFilePath = path;
			m_pEmitter->Create( path.wc_str() );
		}
	}

	bool bLight = m_pProperties[1]->GetValue().GetBool();
	bool bTextureMapping = m_pProperties[2]->GetValue().GetBool();
	m_pEmitter->EnableLighting( bLight );
	m_pEmitter->EnableTextureMapping( bTextureMapping );

}

//--------------------------------------------------------------------------------
// CEPGEmitterParticle
//--------------------------------------------------------------------------------
CEPGEmitterParticle::CEPGEmitterParticle( SP::SPEmitterParticle* pEmitter )
	: CEPGEmitter( pEmitter ), m_pEmitter( pEmitter )
{
	Append( new wxPropertyCategory( L"ParticleEmitter" ) );

	/*
	wxPGChoices etarr;
	etarr.Add( L"Process Spawn rate", 1 );
	etarr.Add( L"Spawned", 2 );
	m_pProperties[0] = Append( new wxEnumProperty( L"Emitter Type", wxPG_LABEL, etarr, 1 ) );
	m_pProperties[1] = Append( new wxIntProperty( L"Max Count", wxPG_LABEL, 20 ) );
	m_pProperties[2] = Append( new wxFloatProperty( L"Spawn Rate", wxPG_LABEL, 1.0f ) );
	m_pProperties[3] = Append( new wxFloatProperty( L"Particle Life Time", wxPG_LABEL, 1.0f ) );

	m_pProperties[1]->Hide( false );
	m_pProperties[2]->Hide( true );
	m_pProperties[3]->Hide( true );
	*/
	m_flastRate = 20.0f;
	m_flastLifeTime = 2.0f;
	m_pProperties[2] = Append( new wxFloatProperty( L"Spawn Rate", wxPG_LABEL, 20.0f ) );
	m_pProperties[3] = Append( new wxFloatProperty( L"Particle Life Time", wxPG_LABEL, 2.0f ) );
	//
	m_strFilePath = L""; 
	Append( new wxPropertyCategory(L"ParticleTexture") );
	m_pProperties[4] = Append( new wxFileProperty( L"Texture path" ) );

	// 
	Append( new wxPropertyCategory(L"ParticleSort") );
	m_pProperties[5] = Append( new wxBoolProperty( L"DepthSort", wxPG_LABEL, false ) );
	
	Append( new wxPropertyCategory(L"ParticleAbsVector") );
	m_pProperties[6] = Append( new wxBoolProperty( L"AbsPos", wxPG_LABEL, true ) );
	m_pProperties[7] = Append( new wxBoolProperty( L"AbsVelo", wxPG_LABEL, true ) );
	m_pProperties[8] = Append( new wxBoolProperty( L"AbsAccel", wxPG_LABEL, true ) );
}

void CEPGEmitterParticle::OnUpdate()
{
	CEPGEmitter::OnUpdate();

	/*
	// ParticleType
	bool bSpawned = m_pProperties[0]->GetValue().GetInteger() == 1;
	m_pProperties[1]->Hide( !bSpawned );
	m_pProperties[2]->Hide( bSpawned );
	m_pProperties[3]->Hide( bSpawned );

	if (bSpawned)
	{
		static int lastCount =  m_pProperties[1]->GetValue().GetInteger();
		int maxCount = m_pProperties[1]->GetValue().GetInteger();
		if ( maxCount < 1 )
		{
			m_pProperties[1]->SetValue(1);
			maxCount = 1;
		}
		if ( lastCount != maxCount )
		{
			m_pEmitter->Create( maxCount );
			lastCount = maxCount;
		}
	}
	else
	{
		static float lastRate = m_pProperties[2]->GetValue().GetDouble();
		static float lastLifeTime = m_pProperties[3]->GetValue().GetDouble();

		float fRate = m_pProperties[2]->GetValue().GetDouble();
		float fLifeTime = m_pProperties[3]->GetValue().GetDouble();
		if ( fRate <= 0.0f )
		{
			m_pProperties[2]->SetValue( 1.0 );
			fRate = 1.0f;
		}
		if ( fLifeTime <= 0.0f )
		{
			m_pProperties[3]->SetValue( 1.0 );
			fLifeTime = 1.0f;
		}

		if ( fRate != lastRate || fLifeTime != lastLifeTime )
		{
			m_pEmitter->Create( fRate, fLifeTime );
			lastLifeTime = fLifeTime;
			lastRate = fRate;
		}
	}
	*/
	float fRate = m_pProperties[2]->GetValue().GetDouble();
	float fLifeTime = m_pProperties[3]->GetValue().GetDouble();
	if ( fRate <= 0.0f )
	{
		m_pProperties[2]->SetValue( 1.0 );
		fRate = 1.0f;
	}
	if ( fLifeTime <= 0.0f )
	{
		m_pProperties[3]->SetValue( 1.0 );
		fLifeTime = 1.0f;
	}

	if ( fRate != m_flastRate || fLifeTime != m_flastLifeTime )
	{
		m_pEmitter->Create( fRate, fLifeTime );
		m_flastLifeTime = fLifeTime;
		m_flastRate = fRate;
	}

	// ParticleTexture
	wxString path = m_pProperties[4]->GetValue().GetString();
	if ( path != m_strFilePath )
	{
		m_strFilePath = path;
		if ( 0 < m_pEmitter->CreateTextureFromFile( path.wc_str() ) )
		{
			m_strFilePath = L"";
			m_pProperties[4]->SetValue( L"" );
		}
	}

	// DepthSort
	bool bSort = m_pProperties[5]->GetValue().GetBool();
	m_pEmitter->EnableDepthSort( bSort );

	bool bAbsPos = m_pProperties[6]->GetValue().GetBool();
	bool bAbsVelo = m_pProperties[7]->GetValue().GetBool();
	bool bAbsAccel = m_pProperties[8]->GetValue().GetBool();
	m_pEmitter->AbsParticlePosition( bAbsPos );
	m_pEmitter->AbsParticleVelocity( bAbsVelo );
	m_pEmitter->AbsParticleAcceleration( bAbsAccel );

}

//--------------------------------------------------------------------------------
// CEPGEmitterBeam
//--------------------------------------------------------------------------------
CEPGEmitterBeam::CEPGEmitterBeam( SP::SPEmitterBeam* pEmitter )
	: CEPGEmitter( pEmitter )
{
	m_pEmitter = pEmitter;

	Append( new wxPropertyCategory(L"BeamEmitter") );

	m_pProperties[0] = Append( new wxBoolProperty( L"EnableNoise", wxPG_LABEL, false ) );
	m_pProperties[1] = Append( new wxIntProperty( L"NumControlPoint", wxPG_LABEL, 10 ) );
	m_pProperties[2] = Append( new wxIntProperty( L"TessellationAmount", wxPG_LABEL, 10 ) );
	m_pProperties[3] = Append( new wxBoolProperty( L"FaceToCamera", wxPG_LABEL, false ) );

	m_strFilePath = L""; 
	Append( new wxPropertyCategory(L"BeamTexture") );
	m_pProperties[4] = Append( new wxFileProperty( L"Texture path" ) );

	Append( new wxPropertyCategory(L"BeamNoise") );
	m_pProperties[5] = Append( new wxFloatProperty( L"NoiseSpeed", wxPG_LABEL, 1.0f ) );
	m_pProperties[6] = Append( new wxFloatProperty( L"NoiseScale", wxPG_LABEL, 1.0f ) );

	Append( new wxPropertyCategory(L"Width") );
	m_pProperties[8] = Append( new wxFloatProperty( L"Beam width", wxPG_LABEL, 1.0f ) );
}

void CEPGEmitterBeam::OnUpdate()
{
	CEPGEmitter::OnUpdate();
	//
	BOOL bEnableNoise = m_pProperties[0]->GetValue().GetBool();
	m_pEmitter->EnableNoise( bEnableNoise );

	//
	int num = m_pProperties[1]->GetValue().GetInteger();
	num = ( num%2 == 0 ) ? num : num - 1;
	num = ( num < 2 ) ? 2 : num;
	num = ( num > 250 ) ? 250 : num;
	m_pProperties[1]->SetValue( num );
	m_pEmitter->Create( num );

	// Tessellation 
	int nTessAmount = m_pProperties[2]->GetValue().GetInteger();
	nTessAmount = nTessAmount > 1 ? nTessAmount : 1;
	nTessAmount = nTessAmount < 64 ? nTessAmount : 64;
	m_pProperties[2]->SetValue( nTessAmount );
	m_pEmitter->SetTessellationAmount( nTessAmount );

	// FaceToCamera
	BOOL bface = m_pProperties[3]->GetValue().GetBool();
	m_pEmitter->FaceToCamera( bface );

	// Texture
	wxString path = m_pProperties[4]->GetValue().GetString();
	if ( path != m_strFilePath )
	{
		m_strFilePath = path;
		if ( 0 < m_pEmitter->CreateTextureFromFile( path.wc_str() ) )
		{
			m_strFilePath = L"";
			m_pProperties[4]->SetValue( L"" );
		}
	}

	// Noise
	float speed = m_pProperties[5]->GetValue().GetDouble();
	float scale = m_pProperties[6]->GetValue().GetDouble();

	speed = ( speed < 0.0f ) ? 1.0f : speed;
	scale = ( scale < 0.0f ) ? 1.0f : scale;

	m_pProperties[5]->SetValue( speed );
	m_pProperties[6]->SetValue( scale );
	m_pEmitter->SetNoise( speed, scale );

	// width
	m_pEmitter->SetWidthScale( m_pProperties[8]->GetValue().GetDouble() );
}


//--------------------------------------------------------------------------------
// CEPGEmitterAnimTrail
//--------------------------------------------------------------------------------
CEPGEmitterAnimTrail::CEPGEmitterAnimTrail( SP::SPEmitterAnimTrail* pEmitter )
	: CEPGEmitter( pEmitter )
{
	m_pEmitter = pEmitter;

	Append( new wxPropertyCategory(L"AnimTrailEmitter") );

	m_pProperties[0] = Append( new wxIntProperty( L"NumControlPoint", wxPG_LABEL, 10 ) );
	m_pProperties[1] = Append( new wxIntProperty( L"TessellationAmount", wxPG_LABEL, 10 ) );
	m_pProperties[2] = Append( new wxBoolProperty( L"AbsHead", wxPG_LABEL, false ) );
	m_pProperties[3] = Append( new wxFloatProperty( L"AnimTrailDuration", wxPG_LABEL, 1.0f ) );
	
	m_strFilePath = L""; 
	Append( new wxPropertyCategory(L"AnimTrailTexture") );
	m_pProperties[4] = Append( new wxFileProperty( L"Texture path" ) );

	AppendVector( L"LeftPos", m_vLeft );
	AppendVector( L"RightPos", m_vRight );
}

void CEPGEmitterAnimTrail::OnUpdate()
{
	CEPGEmitter::OnUpdate();

	//
	int num = m_pProperties[0]->GetValue().GetInteger();
	num = ( num%2 == 0 ) ? num : num - 1;
	num = ( num < 2 ) ? 2 : num;
	num = ( num > 250 ) ? 250 : num;
	m_pProperties[0]->SetValue( num );
	m_pEmitter->Create( num );

	// Tessellation 
	int nTessAmount = m_pProperties[1]->GetValue().GetInteger();
	nTessAmount = nTessAmount > 1 ? nTessAmount : 1;
	nTessAmount = nTessAmount < 64 ? nTessAmount : 64;
	m_pProperties[1]->SetValue( nTessAmount );
	m_pEmitter->SetTessellationAmount( nTessAmount );

	//
	bool bAbsHead = m_pProperties[2]->GetValue().GetBool();
	m_pEmitter->AbsHead( bAbsHead );

	//
	FLOAT fDuration = m_pProperties[3]->GetValue().GetDouble();
	if ( fDuration <= 0.0f )
	{
		fDuration = 1.0f;
		m_pProperties[3]->SetValue( fDuration );
	}
	m_pEmitter->AnimTrailDuration( fDuration );

	//
	UpdateVector( m_vLeft );
	UpdateVector( m_vRight );
	m_pEmitter->SetHead( m_vLeft.m_vValue, m_vRight.m_vValue );

	// Texture
	wxString path = m_pProperties[4]->GetValue().GetString();
	if ( path != m_strFilePath )
	{
		m_strFilePath = path;
		if ( 0 < m_pEmitter->CreateTextureFromFile( path.wc_str() ) )
		{
			m_strFilePath = L"";
			m_pProperties[4]->SetValue( L"" );
		}
	}
}



